package com.morningstar.qs.api.basic.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

public class FTPClientImpl {
	private final static Logger gLogger = Logger.getLogger(FTPClientImpl.class);
	
	private static FTPClient getConnectedFTPClient(String host, int port, String username, String password){
		final FTPClient ftp = new FTPClient();
		gLogger.error("Getting Connection from FTPClient.\nHost:" + host + "\t Port: " + port + "\nUserName:"+username+"\t Password:"+ password);
		boolean isConnected = connectFTPClient(host, port, ftp);
		if(isConnected && checkFTPClientPositive(host, port, username, password, ftp)){
			if (configFTPClient(username, password, ftp)){
				return ftp;
			}
		}
		
		return null;
	}

	private static boolean connectFTPClient(String host, int port, final FTPClient ftp) {
		try {
			if(port>0)
				ftp.connect(host, port);
			else
				ftp.connect(host);
		} catch (IOException e) {
			gLogger.error("FTP server refused connection.\nHost:" + host + "\t Port: " + port);
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException f) {
					f.printStackTrace();
				}
			}
			e.printStackTrace();
			return false;
		} catch (Exception e) {
			gLogger.error("FTP server refused connection.\nHost:" + host + "\t Port: " + port);
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	private static boolean checkFTPClientPositive(String host, int port,
			String username, String password, final FTPClient ftp) {
		int reply = ftp.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			try {
				ftp.disconnect();
			} catch (IOException e) {
				e.printStackTrace();
			}
			gLogger.error("FTP server refused connection.\nHost:" + host + "\t Port: " + port + "\nUserName:"+username+"\t Password:"+ password);
			return false;
		}
		return true;
	}
	
	private static boolean configFTPClient(String username, String password, final FTPClient ftp) {
		try {
			if (!ftp.login(username, password)) {
				ftp.logout();
				gLogger.error("config FTPClient failed.");
				return false;
			}
		} catch (IOException e) {
			gLogger.error("config FTPClient failed.");
			e.printStackTrace();
			return false;
		}

		// System.out.println("Remote system is " + ftp.getSystemType());
		ftp.setUseEPSVwithIPv4(false);
		FTPClientConfig config = new FTPClientConfig();
		config.setLenientFutureDates(true);
		ftp.configure(config);
		
		return true;
	}

	public static InputStream getFileInputStreamFromRemoteFtp(String host, int port, String username, String password, String path){
		FTPClient ftp = getConnectedFTPClient(host, port, username, password);
		try {
			gLogger.info("Getting FTP file: "+path);
			InputStream  input = ftp.retrieveFileStream(path);
			return input;
		} catch (IOException e) {
			gLogger.error("Can't get InputStream from path \""+path+"\"");
			e.printStackTrace();
		}
		return null;
	}
	
	public static boolean putFile(String host, int port, String username, String password, String location, String remoteName) 
			throws FileNotFoundException, IOException{
		
		FTPClient ftp = getConnectedFTPClient(host, port, username, password);

		File local = new File(location);
		return ftp.storeFile(remoteName,new FileInputStream(local));
	}
	
	public static void main(String[] args) {
		String host = "ftp.morningstar.com";
		final int port = 21;
		String username = "qs-euam";
		String password = "wqF5qzVQ";
		String path = "data/TAB.csv";
		
		InputStream in = getFileInputStreamFromRemoteFtp(host, port, username, password, path);
		
		StringBuilder sb = new StringBuilder();
		BufferedReader reader = new BufferedReader(new InputStreamReader(in));
		String line;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line).append("\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				reader.close();
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		
		System.out.println(sb.toString());
		
	}
	
	
/**
	public static void main(String... strings) {
		String host = "ftp.morningstar.com";
		final int port = 21;
		String username = "qs-euam";
		String password = "wqF5qzVQ";

		final FTPClient ftp;
		ftp = new FTPClient();

		try {
			ftp.connect(host, port);
		} catch (IOException e) {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException f) {
					// do nothing
				}
			}
		} catch (Exception e) {

		}
		System.out.println("Connected to " + host + " on " + ftp.getRemotePort());

		// After connection attempt, you should check the reply code to
		// verify
		// success.
		int reply = ftp.getReplyCode();

		if (!FTPReply.isPositiveCompletion(reply)) {
			try {
				ftp.disconnect();
			} catch (IOException e) {
				e.printStackTrace();
			}
			System.err.println("FTP server refused connection.");
			System.exit(1);
		}

		boolean error = false;

		__main: try {
			if (!ftp.login(username, password)) {
				ftp.logout();
				error = true;
				break __main;
			}

			System.out.println("Remote system is " + ftp.getSystemType());
			ftp.setUseEPSVwithIPv4(false);
				FTPClientConfig config = new FTPClientConfig();
				config.setLenientFutureDates(true);
				ftp.configure(config);

			for (FTPFile f : ftp.listFiles("data")) {
//				System.out.println(f.getRawListing());
//				System.out.println(f.toFormattedString());
				if(f.isFile()) {
					System.out.println("File name: "+f.getName()+" Created date: "+ DatetimeUtil.format(f.getTimestamp().getTime(), DatetimeUtil.DEFAULT_DATE_TIME));
					OutputStream output;

					File path=new File("data");
					if(!path.isDirectory()) {
						path.mkdirs();
					}
					File file=new File("data/"+f.getName());
					if(file.exists()) file.delete();
					String paths=file.getAbsolutePath();
					System.out.println(paths);
					
//					file.createTempFile(prefix, suffix)
					
					file.createNewFile();
					output = new FileOutputStream(file);

					ftp.retrieveFile("data/"+f.getName(), output);

					output.close();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	*/
}
